Use the pinch manipulator to enable users to zoom and rotate nodes in your Kanzi application. To calculate the amount by which to zoom and rotate a node, the pinch gesture continuously tracks the position and distance between two fingers that move on the device screen.
Use the multi-click manipulator to enable users to multi-click or multi-tap nodes in your Kanzi application. You can set in the multi-click manipulator the number of taps and the maximum amount of time that can lapse between the taps for Kanzi to interpret the taps as a multi-tap gesture.
In this step you first use the pinch manipulator to enable zooming and rotating of the map. Then you use the multi-click manipulator to enable resetting the position, zoom level, and rotation angle of the map.
You deploy the tutorial application to an Android device, because the pinch gesture requires multitouch support.
In this section you create and use the pinch manipulator to zoom and rotate the map when the user pinches the map.
To zoom and rotate the map:
PanZoomTap
class define the handlers for the pinch messages:private: ... // Define the handler for thePinchManipulator::StartedMessage
message from the 2D nodes // that have an input manipulator which generates pinch messages. // This handler prepares a 2D node for a pinch gesture. void onPinchStarted(PinchManipulator::StartedMessageArguments& messageArguments) { // Get from the message arguments the node that the user pinches. Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource()); // Store the initial value of the Render Transformation property Scale property field. SRTValue2D nodeTransform = mapNode->getRenderTransformation(); m_pinchInitialScaleFactor = nodeTransform.getScale().getX() - 1.0f; // Calculate a minimum scale value based on the size of the application screen. ScreenSharedPtr screen = getScreen(); m_minScale = max(getScreen()->getActualWidth() / mapNode->getActualWidth(), screen->getActualHeight() / mapNode->getActualHeight()); } // Define the handler for thePinchManipulator::MovedMessage
message from the 2D nodes // that have an input manipulator which generates pinch messages. // This scales and rotates a 2D node for the amount of the pinch gesture. void onPinchMoved(PinchManipulator::MovedMessageArguments& messageArguments) { // Get from the message arguments the node that the user pinches. Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource()); // Get the scale and rotation from the message arguments. float scaleDelta = messageArguments.getScale(); float rotateDelta = messageArguments.getRotation(); // Calculate the scale by adding the initial scale to the pinch value. // Restrict the scale so that the map cannot be smaller than the application screen size. float scale = max(m_minScale, scaleDelta + m_pinchInitialScaleFactor); // Get the Render Transformation property of the Map node. SRTValue2D mapRenderSRT = mapNode->getRenderTransformation(); // Apply the rotation. mapRenderSRT.rotate(rotateDelta); // Apply the scale. mapRenderSRT.setScale(Vector2(scale, scale)); // Get the world transformation of the Map node. // You use this in the next step of the tutorial. Matrix3x3 mapWorldTransform = mapNode->getWorldTransform(); SRTValue2D mapWorldSRT = *SRTValue2D::create(mapWorldTransform); // Apply the new render transformation to the Map node. mapNode->setRenderTransformation(mapRenderSRT); } // Define a member variable for the initial scale factor of the pinch gesture. float m_pinchInitialScaleFactor; // Define a member variable for the minimum scale value. float m_minScale; };
PanZoomTap
class add the constructor and set the initial scale factor for the pinch gesture:public: PanZoomTap() : m_pinchInitialScaleFactor(0.0f) { } ...
onProjectLoaded
() function create a PinchManipulator
manipulator and subscribe to its messages at the Map node:virtual void onProjectLoaded() KZ_OVERRIDE { ... // Create an input manipulator that generates pinch messages. PinchManipulatorSharedPtr pinchManipulator = PinchManipulator::create(domain); // Add the input manipulator to the Map node. mapNode->addInputManipulator(pinchManipulator); // Subscribe to thePinchManipulator::StartedMessage
message at the Map node. // The PinchManipulator generates this message when the user presses two fingers on the Map node. mapNode->addMessageHandler(PinchManipulator::StartedMessage, bind(&PanZoomTap::onPinchStarted, this, placeholders::_1)); // Subscribe to thePinchManipulator::MovedMessage
message at the Map node. // ThePinchManipulator
generates this message when the scale or rotation threshold is exceeded // and when the tracked touches move between updates. mapNode->addMessageHandler(PinchManipulator::MovedMessage, bind(&PanZoomTap::onPinchMoved, this, placeholders::_1)); }
On your Android device use the pinch gesture to zoom and rotate the map.
The map rotates around its center point because the origin of the Map node is set to the center.
In this section you use the multi-click manipulator to reset the position, zoom level, and rotation angle of the map when the user double-taps the map.
To reset the position, zoom level, and rotation:
PanZoomTap
class define the handler for the multi-click message:private:
...
// Define the handler for the MultiClickManipulator::MultiClickMessage
message from the nodes that have
// an input manipulator which generates the multi-click message when the user double-taps the node.
void onNodeDoubleTapped(MultiClickManipulator::MultiClickMessageArguments& messageArguments)
{
// Get from the message arguments the node that the user double-taps.
Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
// Remove the Render Transformation property of the node.
// This way you reset the position, zoom level, and rotation angle of the Map node.
mapNode->removeLocalValue(Node2D::RenderTransformationProperty);
}
...
};
onProjectLoaded
() function create and configure a MultiClickManipulator
manipulator and subscribe to its message at the Map node:virtual void onProjectLoaded() KZ_OVERRIDE { ... // Create an input manipulator that generates the multi-click message. MultiClickManipulatorSharedPtr multiClickManipulator = MultiClickManipulator::create(domain); // Add the input manipulator to the Map node. mapNode->addInputManipulator(multiClickManipulator); // By default the input manipulator recognizes two taps as a double-tap gesture. // To use a different number of taps, use theMultiClickManipulator::setExpectedClicks
function. // For example, to set the input manipulator to recognize three taps as a multi-click gesture pass 3 to the function. // multiClickManipulator->setExpectedClicks(3); // Set the timeout of the double-tap to 300 ms. If the time between two taps does not exceed this value, // the input manipulator recognizes these taps as a double-tap gesture. The default timeout is 250 ms. multiClickManipulator->setTimeout(chrono::milliseconds(300)); // Subscribe to theMultiClickManipulator::MultiClickMessage
message at the Map node. // TheMultiClickManipulator
manipulator generates this message when the user double-taps the node. mapNode->addMessageHandler(MultiClickManipulator::MultiClickMessage, bind(&PanZoomTap::onNodeDoubleTapped, this, placeholders::_1)); }
To learn more about the pinch manipulator, see Using the pinch manipulator.
To learn more about the multi-click manipulator, see Using the multi-click manipulator.
To learn more about deploying Kanzi applications to Android, see Deploying Kanzi applications to Android.